IAM ロールのアクティブなセッションの無効化をする時にインラインポリシーを PUT するのは誰なのか
コンバンハ、千葉(幸)です。
IAM コンソールでは、IAM ロールの詳細画面で「アクティブなセッションの無効化」というボタンが用意されています。
これのことです。
説明書きにはこのように書かれています。
[Revoke active sessions] (アクティブセッションを取り消す) を 選択した場合、このロールに AWSRevokeOlderSessions という名前のインラインポリシーが IAM によってアタッチされます。このポリシーでは、このロールにおける現在アクティブなすべてのセッションへの権限が拒否されます。このロールで、継続して新しいセッションを作成することができます。このアクションを後で元に戻す必要がある場合、インラインポリシーを削除することができます。 詳細はこちら
「インラインポリシーが IAM によってアタッチされます。」の記述があります。え? IAM 自体が何かしてくれるの?とワクワクさが頭をもたげてきます。
さらにこの操作について書かれた AWS ドキュメント *1を見ると以下の記述があります。
このトピックの手順を使用してロールのアクセス許可を取り消す場合、AWS は、すべてのアクションへのすべてのアクセス許可を拒否するロールに新しいインラインポリシーをアタッチします。
「AWS は〜アタッチします。」と来ました。
インラインポリシーがアタッチされることは分かりましたが、その実行主体は果たして何なのか? 例えば IAM というサービス自体がプリンシパルだったりするのか?といった部分が気になってきます。ワクワクしてきます。
これはもう実際にコンソールからセッションの無効化を行い、その履歴を CloudTrail から確認するしかないですね!!!
実行元は普通にコンソールの操作者でした
言われてみればそうだよな、という結果でした。
試してみたところ、「コンソールを操作する IAM プリンシパル」による API コールとして Trail に記録されていました。ここでの IAM プリンシパルとは、例えばコンソールにサインインした IAM ユーザーであるとか、スイッチロールした場合にはそのロールセッションのことを言っています。
あっけなく答えが分かってしまいましたが、せっかくなので以下を試してみます。
- コンソールを操作する IAM プリンシパルの権限を絞ったらどうなるか
- AWS CLI で同じことやるにはどうするか
その前に少しおさらいもします。
IAM ロールのアクティブなセッションを無効化するとは
IAM ロールを引き受ける(AssumeRole)ことで、一時的に有効なクレデンシャルが発行されます。一時的なクレデンシャルは以下を含みます。
- アクセスキー
- シークレットアクセスキー
- セッショントークン
IAM ロールを引き受けたプリンシパル(IAM ユーザーなど)は、このクレデンシャルを利用することで一定期間 IAM ロールの権限を持つように振る舞えます。ロールを引き受けたセッションは有限(最大12時間)であり、その有効期間はセッショントークンにより制御されています。
ここで、一時的なクレデンシャルが何らかの形で悪意のあるユーザーの手に渡ったとします。悪意のあるユーザーはセッショントークンの有効期限が切れるまで当該 IAM ロールの権限を利用してアクションを実行できてしまいます。
この時に有効な対応策が「アクティブなセッションの無効化」です。この操作を実行すると、対象の IAM ロールに以下のポリシーがインラインポリシーとしてアタッチされます。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Action": [ "*" ], "Resource": [ "*" ], "Condition": { "DateLessThan": { "aws:TokenIssueTime": "[policy creation time]" # [policy creation time]には無効化を実行した時刻が入ります。 } } } ] }
aws:TokenIssueTime
という、セッショントークンが発行された時刻を評価する条件キーが使用されています。「アクティブなセッションの無効化」より前に発行されたセッショントークンを利用するリクエストに対しては、すべてのアクションを拒否するという内容になっています。
これにより、セッションの有効期間を迎える前に明示的にセッションによるリクエストを無効化できます。セッショントークンの発行時刻を評価対象としているため、「アクティブなセッションの無効化」後に発行されたセッショントークンは影響を受けません。
アクティブなセッションの無効化をやってみる
コンソール上で操作する際の流れを確認しておきます。
今回は以下条件で試行します。
- コンソールの操作者:
arn:aws:sts::012345678910:assumed-role/cm-chiba.yukihiro/cm-chiba.yukihiro
- IAM ユーザー
cm-chiba.yukihiro
が IAM ロールcm-chiba.yukihiro
にスイッチロールした状態
- IAM ユーザー
- セッションの無効化対象のロール:
test-role-kunn
IAM ロールtest-role-kunn
の詳細画面「セッションを取り消す」タブから「アクティブなセッションの無効化」を押下します。
チェックボックスにチェックを入れ、「アクティブなセッションの無効化」を実行します。
「アクティブなセッションが正常に取り消されました。」の表示が画面上部に出ます。
IAM ロールtest-role-kunn
にアタッチされたポリシーを確認すると、AWSRevokeOlderSessions
というインラインポリシーが追加でアタッチされています。
ポリシーには「アクティブなセッションの無効化」を実行した時刻が挿入されています。
「アクティブなセッションの無効化」を実行した際の流れが確認できました。
アクティブなセッションの無効化を CloudTrail イベントで確認する
上記の操作の内訳を CloudTrail イベントで確認します。IAM に関するイベントであるため、バージニア北部リージョンで確認してください。
実際に確認できたイベントは以下の通りです。
{ "eventVersion": "1.08", "userIdentity": { "type": "AssumedRole", "principalId": "AROAQ3BIIH732QEGJXBGU:cm-chiba.yukihiro", "arn": "arn:aws:sts::012345678910:assumed-role/cm-chiba.yukihiro/cm-chiba.yukihiro", "accountId": "012345678910", "accessKeyId": "ASIAQ3BIIH73VL2WN65W", "sessionContext": { "sessionIssuer": { "type": "Role", "principalId": "AROAQ3BIIH732QEGJXBGU", "arn": "arn:aws:iam::012345678910:role/cm-chiba.yukihiro", "accountId": "012345678910", "userName": "cm-chiba.yukihiro" }, "webIdFederationData": {}, "attributes": { "creationDate": "2023-06-18T14:37:11Z", "mfaAuthenticated": "true" } } }, "eventTime": "2023-06-18T14:38:32Z", "eventSource": "iam.amazonaws.com", "eventName": "PutRolePolicy", "awsRegion": "us-east-1", "sourceIPAddress": "xx.xx.xx.xx", "userAgent": "AWS Internal", "requestParameters": { "roleName": "test-role-kunn", "policyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Deny\",\"Action\":[\"*\"],\"Resource\":[\"*\"],\"Condition\":{\"DateLessThan\":{\"aws:TokenIssueTime\":\"2023-06-18T14:38:32.273Z\"}}}]}", "policyName": "AWSRevokeOlderSessions" }, "responseElements": null, "requestID": "9949124e-3bc4-4831-9017-9e6b15a3d84e", "eventID": "fa147c98-e525-466c-b7f8-015f8507833d", "readOnly": false, "eventType": "AwsApiCall", "managementEvent": true, "recipientAccountId": "012345678910", "eventCategory": "Management", "sessionCredentialFromConsole": "true" }
arn:aws:sts::012345678910:assumed-role/cm-chiba.yukihiro/cm-chiba.yukihiro
が、IAM ロールtest-role-kunn
に対して特定のポリシーをインラインポリシーとしてアタッチ(PutRolePolicy
)していることが分かります。
「アクティブなセッションの無効化」とは、言ってみれば上記のアクションを行うだけのものです。
アクティブなセッションの無効化を失敗させてみる
「アクティブなセッションの無効化」は「特定のインラインポリシーの PUT」をするだけなので、そのアクションをポリシーで禁止すれば操作は失敗します。
マネジメントコンソールを操作する際のスイッチロール先である IAM ロールcm-chiba.yukihiro
に以下のポリシーをアタッチします。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Action": "iam:PutRolePolicy", "Resource": "*" } ] }
この状態で先ほどと同じように「アクティブなセッションの無効化」を試みると、以下のように失敗します。
セッションの取り消しに失敗しました。
User: arn:aws:sts::012345678910:assumed-role/cm-chiba.yukihiro/cm-chiba.yukihiro is not authorized to perform: iam:PutRolePolicy on resource: role test-role-kunn with an explicit deny in an identity-based policy
明示的に禁止したいケースはあまりない気がしますが、「いざ実施しようと思ったらiam:PutRolePolicy
の権限が足りない」ということはありそうです。覚えておきましょう。
AWS CLI でアクティブなセッションの無効化をやってみる
マネジメントコンソールだけでなく AWS CLI でもアクティブセッションの無効化をやってみます。
今回は IAM ロールcm-chiba.yukihiro
を対象に行なってみます。挙動の確認のため、cm-chiba.yukihiro
にスイッチロールした状態にしておきます。
↑なお、cm-chiba.yukihiro
にはAdministratorAcess
がアタッチされています。
AWS CLI aws iam put-role-policy
コマンドを使用してインラインポリシーをアタッチします。 *2
ポリシードキュメント内の時刻の部分をいい感じに設定できれば *3、あとは通常通りインラインポリシーをアタッチする操作をすれば問題ありません。
今回は以下のコマンドを実行しました。(macOS + zsh と AWS CloudShell + bash で動作確認済みです。)
% policy=$(cat <<EOM { "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Action": [ "*" ], "Resource": [ "*" ], "Condition": { "DateLessThan": { "aws:TokenIssueTime": "$(date -u +%Y-%m-%dT%H:%M:%SZ)" } } } ] } EOM ) % aws iam put-role-policy\ --role-name cm-chiba.yukihiro\ --policy-name AWSRevokeOlderSessions\ --policy-document "$policy"
上記の操作を実行後、ブラウザをリロードすると以下のようにエラーが発生しました。
アクセス拒否
iam:GetRole に対する許可がありません。アクセスをリクエストするには、次のテキストをコピーして AWS 管理者に送信してください。 アクセス拒否エラーのトラブルシューティングに関する詳細を確認してください。
セッショントークンの発行はスイッチロール実行時に行われている(はずな)ので、現在のスイッチロールセッションではすべてのアクションが拒否されます。他のサービスの画面を開いても同様に参照権限不足のエラーが出ます。
一度スイッチバック(スイッチロール元の IAM ユーザーに戻る)し再度cm-chiba.yukihiro
にスイッチロールすると、また問題なく参照できるようになります。
AWS CLI によりAWSRevokeOlderSessions
がアタッチされていることも分かります。
同名のインラインポリシーがある場合に「無効化」をするとどうなる?
上記の状態から更にコンソールで「アクティブなセッションの無効化」を行うと、同名のインラインポリシーはふたつ同時にアタッチできないため、AWSRevokeOlderSessions
のポリシードキュメントが上書きされる挙動になります。
終わりに
IAM ロールのアクティブなセッションの無効化を実行する際にインラインポリシーをアタッチするのは誰なのか、という話でした。
「アクティブなセッションの無効化」という特別な機能のように見えますが、実態はインラインポリシーをアタッチしているだけであり、コンソールの操作者によるアタッチである、という結果になりました。
無効化操作の実行時刻をうまくポリシードキュメントに組み込んでくれたり、IAM ロールの詳細画面から導線を用意してくれている部分が便利だな、と思っておきましょう。
AWSRevokeOlderSessions
というインラインポリシーは、無効化以降に生成されたセッションにおいては影響を与えないためそのままにしても特に問題はありません。とは言え意味のないポリシーがくっついたままになっているのは気になってしまうので、「セッション無効化の履歴を残しておきたい」といった理由がない限りはデタッチすることを個人的にお勧めします。
以上、 チバユキ (@batchicchi) がお送りしました。
脚注
- IAM ロールの一時的なセキュリティ認証情報の取り消し - AWS Identity and Access Management ↩
- AWS CLI の実行主体は特に問いません。 ↩
- コンソールからセッションの無効化を行う際はミリ秒以下3桁の時刻まで設定されていますが、今回はミリ秒以下までは指定しない書き方にしました。 ↩